package it.traveldream.EJB;

import it.traveldream.EJB.DTO.GiftListDTO;
import it.traveldream.EJB.DTO.UtenteDTO;
import it.traveldream.EJB.entities.GiftList;
import it.traveldream.EJB.entities.Group;
import it.traveldream.EJB.entities.User;
import it.traveldream.utility.DTO2Entities;
import it.traveldream.utility.Entities2DTO;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;

/**
 * Session Bean implementation class UtenteEJBImpl
 */
@Stateless
public class UtenteEJBImpl implements UtenteEJB {



	@PersistenceContext
	EntityManager em;

	public UtenteEJBImpl() {

	}

	public UtenteEJBImpl(EntityManager emg){
		if(em==null){
			em=emg;
		}
	}

	/**
	 * Implemeta la registrazione di un nuovo cliente
	 * Aggiunge infatti un nuovo {@link User} nella tabella corrispondente
	 * 
	 * @param user = l'{@link UtenteDTO} creato dalle informazioni inserite
	 *
	 */
	@Override
	public void addUser(UtenteDTO user) throws Exception {

		User u=new User();

		if(isAlreadyUser(user.getUsername())){
			throw new Exception("USERNAME GIA USATO: sticazzi!");
		}
		
		user.setPassword(sha256(user.getPassword()));
		
		java.sql.Date data = new java.sql.Date(user.getDataNascitaAsDate().getTime());
		
		//u=DTO2Entities.convertUtenteDTO(user,getAllGruppi());

		try{
			int rows = em.createNativeQuery("INSERT INTO users (userid,password,email,nome,cognome,data_nascita) VALUES ('"+user.getUsername()+"' , '"+user.getPassword()+
					"' , '"+user.getEmail()+"' , '"+user.getNome()+"' , '"+user.getCognome()+"' , '"+data+"')").executeUpdate();
			if(rows!=1){
				throw new Exception("cazzo inserimento demmerda user "+rows);
			}
			List<User> userz=em.createQuery("Select u FROM User u ORDER BY u.idUtente DESC").getResultList();
			u=userz.get(0);
			/*
			int rowz = em.createNativeQuery("INSERT INTO user_group (id_utente,id_gruppo,USERID,GROUPID) VALUES ("+u.getIdUtente()+" , "+
					"2 , '"+u.getUserid()+"' , 'USERS')").executeUpdate();
			if(rowz!=1){
				throw new Exception("cazzo inserimento demmerda user_group "+rowz);
			}*/
			/*
			em.persist(u);
			em.detach(u);*/
		}catch(Exception ex){
			throw new Exception("ERRORE INSERIMENTO NUOVO UTENTE: " + ex.getMessage());
		}
	}
	/**
	 * trova la funzione di hash
	 * @param base - la password normale
	 * @return - la password dopo la funzione di hash
	 */
	private String sha256(String base) {
	    try{
	        MessageDigest digest = MessageDigest.getInstance("SHA-256");
	        byte[] hash = digest.digest(base.getBytes("UTF-8"));
	        StringBuffer hexString = new StringBuffer();

	        for (int i = 0; i < hash.length; i++) {
	            String hex = Integer.toHexString(0xff & hash[i]);
	            if(hex.length() == 1) hexString.append('0');
	            hexString.append(hex);
	        }

	        return hexString.toString();
	    } catch(Exception ex){
	       throw new RuntimeException(ex);
	    }
	}
	
	/**
	 * Ritorna la {@link GiftListDTO} di un dato {@link UtenteDTO}
	 * 
	 * @param ut = l'{@link UtenteDTO} passato
	 * 
	 * @return l'{@link ArrayList} di {@link GiftListDTO}
	 */
	@Override
	public ArrayList<GiftListDTO> getGiftListUser(UtenteDTO ut){
		ArrayList<GiftListDTO> result = new ArrayList<GiftListDTO>();
		List<GiftList> lg;
		Iterator<GiftList> ilg;
		
		List<User> lu = getAllUtenti();
		
		int param = getIdFromUsername(ut.getUsername());
		
		lg = em.createQuery("SELECT g FROM GiftList g WHERE g.idUtente= :param").setParameter("param", param).getResultList();
		
		ilg = lg.iterator();
		while(ilg.hasNext()){
			result.add(Entities2DTO.convertGiftList(ilg.next(), lu, em));
		}
		
		return result;
	}

	/**
	 * Cerca se nella tabella degli {@link Utenti} ��� gi��� presente un utente con il dato username
	 * 
	 * @param username = la stringa contenente l'username
	 * 
	 * @return {@link true} se ��� gi��� presente {@link false} altrimenti
	 */
	@Override
	public boolean isAlreadyUser(String username){

		boolean ret=false;

		if(!em.createQuery("SELECT u FROM User u WHERE u.userid= :uid").setParameter("uid", username).getResultList().isEmpty()){
			ret=true;
		}

		return ret;

	}

	public List<User> getAllUtenti(){
		List<User> ret;

		ret = em.createQuery("SELECT u FROM User u").getResultList();

		return ret;
	}

	public List<Group> getAllGruppi(){
		List<Group> ret;

		ret = em.createQuery("SELECT g FROM Group g").getResultList();

		return ret;
	}
	
	/**
	 * Metodo che ritorna un id dato uno username
	 * 
	 * @param username = lo username ricevuto di cui trovare l'idUtente associato
	 *
	 * @return l'idUtente associato
	 */
	public int getIdFromUsername(String username){
		int retId=0;
		Iterator<User> iu;
		
		System.out.println("lo username:"+username);
		
		List<User> lista = em.createQuery("SELECT u FROM User u WHERE u.userid= :username").setParameter("username", username).getResultList();
		
		iu = lista.iterator();
		if(iu.hasNext()){
			retId = iu.next().getIdUtente();
		}
		
		return retId;
	}
	
	/**
	 * recupera lo username dato in ingresso l'id del cliente
	 * 
	 * @param iD
	 * @return- lo username
	 */
	public String getUsernameFromId(int iD){
		
		String result = new String();
		
		Iterator<User> iu;
		List<User> lista = em.createQuery("SELECT u FROM User u WHERE u.idUtente=" + iD).getResultList();
		
		iu = lista.iterator();
		if(iu.hasNext()){
			result = iu.next().getUserid();
		}
		
		
		return result;
		
	}

}
